package cz.najman.emdroid.provider;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import cz.najman.emdroid.mappings.Event;
import cz.najman.emdroid.mappings.EventInstitutionManager;
import cz.najman.emdroid.mappings.Institution;
import cz.najman.emdroid.mappings.PaymentInformation;
import cz.najman.emdroid.mappings.RegistrationState;
import cz.najman.emdroid.mappings.User;
import cz.najman.emdroid.utils.WhereClauseBuilder;

/**
 * @author Lukáš Najman
 */
public class EMDroidDataProvider extends ContentProvider {

	public static final String AUTHORITY = "cz.najman.provider.EMDroid";
	WhereClauseBuilder mWCB = WhereClauseBuilder.getInstance();

	private DatabaseHelper mDbHelper;
	public static final UriMatcher mUriMatcher;

	@Override
	public boolean onCreate() {
		final Context context = getContext();
		mDbHelper = new DatabaseHelper(context);
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,	String[] selectionArgs, String sortOrder) {

		final SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();

		final int match = mUriMatcher.match(uri);
		String id;

		final SQLiteDatabase database = mDbHelper.getReadableDatabase();
		
		switch (match) {
		/* EVENTS */
		case EVENTS_ID:
			id = uri.getPathSegments().get(1);
			queryBuilder.setTables(Event.TABLE_NAME);
			queryBuilder.appendWhere(Event._ID + "=" + id);
			break;
		case EVENTS_REGISTERED:
			queryBuilder.setTables(DatabaseView.VIEW_REG_STATES_EVENTS);
			break;
		case EVENTS_AVAILABLE:				
			
			String sql = "SELECT events._id as _id, event_name, registration_start, registration_end, start_date, end_date FROM events " +
						"JOIN event_managers ON events._id = event_managers.event_id WHERE visible LIKE 'true' AND inst_where " +
					"EXCEPT SELECT events._id as _id, event_name, registration_start, registration_end, start_date, end_date FROM events " +
						"JOIN registration_states ON events._id = registration_states.event_id WHERE visible LIKE 'true';";
			sql = sql.replaceAll("inst_where", selection);
			
			Cursor cursor = database.rawQuery(sql, null);			
			return cursor;
//			String currentTime = String.valueOf(new Date().getTime());
//			String where = mWCB.buildWhereClause(
//					new String[] {Event.REGISTRATION_START, Event.REGISTRATION_END}, 
//					new String[] {currentTime, currentTime}, 
//					new String[] {WhereClauseBuilder.LESS_THEN_OR_EQUAL, WhereClauseBuilder.GRATER_THEN_OR_EQUAL});
			
			//queryBuilder.appendWhere(where);
			//break;
		case EVENTS_MANAGEABLE:
			//TODO 		
			break;
			
		/* USERS */
		case USERS:	
		case USERS_FOR_EVENT:			
		case USERS_FOR_INSTITUTION:	
			queryBuilder.setTables(User.TABLE_NAME);			
			break;
		case USERS_ID:
			id = uri.getPathSegments().get(1);
			queryBuilder.setTables(User.TABLE_NAME);
			queryBuilder.appendWhere(User._ID + " = " + id);
			break;
		case USERS_EMAIL:
			id = uri.getPathSegments().get(2);
			queryBuilder.setTables(User.TABLE_NAME);
			queryBuilder.appendWhere(User.EMAIL + " LIKE '" + id + "'");
			break;			
			
		/* PAYMENT INFORMATIONS */	
		case PAYMENT_INFORMATIONS:	
			queryBuilder.setTables(PaymentInformation.TABLE_NAME);
			break;
		case PAYMENT_INFORMATIONS_ID:
			id = uri.getPathSegments().get(1);
			queryBuilder.setTables(PaymentInformation.TABLE_NAME);
			queryBuilder.appendWhere(PaymentInformation._ID + " LIKE '" + id + "'");
			break;
		case PAYMENT_VALUES:
			queryBuilder.setTables(PaymentInformation.TABLE_NAME);
			queryBuilder.appendWhere(PaymentInformation.VALUE_TYPE + " LIKE 'P'");
			break;
		case STORNO_VALUES:
			queryBuilder.setTables(PaymentInformation.TABLE_NAME);
			queryBuilder.appendWhere(PaymentInformation.VALUE_TYPE + " LIKE 'S'");				
			break;
			
		case REGISTRATION_STATES:
			queryBuilder.setTables(RegistrationState.TABLE_NAME);
			break;
		case REGISTRATION_STATES_ID:
			id = uri.getPathSegments().get(1);
			queryBuilder.setTables(RegistrationState.TABLE_NAME);
			queryBuilder.appendWhereEscapeString(RegistrationState._ID + "=" + id);
			break;
		case REGISTRATION_STATES_FOR_USER:
			queryBuilder.setTables(DatabaseView.VIEW_REG_STATES_EVENTS);
			break;
		case REGISTRATION_STATES_FOR_EVENT:
			queryBuilder.setTables(DatabaseView.VIEW_REG_STATES_EVENTS);						
			break;
			
		/*	EVENT INSTITUTION MANAGERS */
		case EVENT_INSTITUTION_MANAGERS_ID:
			id = uri.getPathSegments().get(1);
			queryBuilder.setTables(EventInstitutionManager.TABLE_NAME);
			queryBuilder.appendWhereEscapeString(EventInstitutionManager._ID + "=" + id);
			break;
		case EVENT_INSTITUTION_MANAGERS_FOR_USER:
			//TODO
			break;
		case EVENT_INSTITUTION_MANAGERS_FOR_EVENT:
			//TODO
		case EVENT_INSTITUTION_MANAGERS_FOR_INSTITUTION:
			//TODO
			break;
		
		/* INSTITUTIONS */
		case INSTITUTIONS_ID:
			id = uri.getPathSegments().get(1);
			queryBuilder.setTables(Institution.TABLE_NAME);
			queryBuilder.appendWhereEscapeString(Institution._ID + "=" + id);
			break;
		case INSTITUTIONS:
			queryBuilder.setTables(Institution.TABLE_NAME);			
			break;
		case INSTITUTIONS_MANAGEABLE_BY_USER:
			//TODO
			break;
		case INSTITUTIONS_FOR_EVENT:
			//TODO
			break;		
		}		

		final Cursor cursor = queryBuilder.query(database, projection, selection, selectionArgs, null, null, sortOrder);
		getContext().getContentResolver().notifyChange(uri, null);

		return cursor;

	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		
		final SQLiteDatabase database = mDbHelper.getWritableDatabase();
		
		final int match = mUriMatcher.match(uri);
		
		switch (match) {
		/* EVENTS */
		case EVENTS_ID:		
		case EVENTS_AVAILABLE:
		case EVENTS_REGISTERED:
		case EVENTS_MANAGEABLE:
			database.insertWithOnConflict(Event.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);			
			break;
			
		/* USERS */
		case USERS: 	
		case USERS_ID:
		case USERS_EMAIL:
		case USERS_FOR_EVENT:
		case USERS_FOR_INSTITUTION:	
			database.insertWithOnConflict(User.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);									
			break;
			
		/* PAYMENT INFORMATIONS */	
		case STORNO_VALUES:	
		case PAYMENT_VALUES:
		case PAYMENT_INFORMATIONS:
		case PAYMENT_INFORMATIONS_ID:		
			database.insertWithOnConflict(PaymentInformation.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);				
			break;
		
		/* REGISTRATION STATES */
		case REGISTRATION_STATES:	
		case REGISTRATION_STATES_ID:
		case REGISTRATION_STATES_FOR_USER:
		case REGISTRATION_STATES_FOR_EVENT:
			database.insertWithOnConflict(RegistrationState.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);							
			break;
			
		/*	EVENT INSTITUTION MANAGERS */
		case EVENT_INSTITUTION_MANAGERS_ID:
		case EVENT_INSTITUTION_MANAGERS_FOR_USER:
		case EVENT_INSTITUTION_MANAGERS_FOR_EVENT:
		case EVENT_INSTITUTION_MANAGERS_FOR_INSTITUTION:	
			database.insertWithOnConflict(EventInstitutionManager.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);	
			break;
		
		/* INSTITUTIONS */
		case INSTITUTIONS:	
		case INSTITUTIONS_ID:		
		case INSTITUTIONS_FOR_EVENT:
		case INSTITUTIONS_MANAGEABLE_BY_USER:		
			database.insertWithOnConflict(Institution.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);
			break;		
		}
		getContext().getContentResolver().notifyChange(uri, null);
		
		return null;
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {

		final SQLiteDatabase database = mDbHelper.getWritableDatabase();

		final int match = mUriMatcher.match(uri);
		int retVal;		

		switch (match) {
		
		default:
			retVal = 0;
			break;
		}

		return retVal;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {

		final SQLiteDatabase database = mDbHelper.getWritableDatabase();

		final int match = mUriMatcher.match(uri);
		int retVal;

		switch (match) {
		
		default:
			retVal = 0;
			break;
		}

		return retVal;
	}

	@Override
	public String getType(Uri uri) {

		final int match = mUriMatcher.match(uri);

		switch (match) {
			/* EVENTS */
			case EVENTS_ID:
				return Event.CONTENT_TYPE_ITEM;
			case EVENTS_REGISTERED:
			case EVENTS_AVAILABLE:
			case EVENTS_MANAGEABLE:
				return Event.CONTENT_TYPE_DIR;			
				
			/* USERS */
			case USERS:
			case USERS_FOR_EVENT:
			case USERS_FOR_INSTITUTION:	
				return User.CONTENT_TYPE_DIR;
			case USERS_ID:
			case USERS_EMAIL:
				return User.CONTENT_TYPE_ITEM;
				
			/* PAYMENT INFORMATIONS */	
			case PAYMENT_INFORMATIONS_ID:
				return PaymentInformation.CONTENT_TYPE_ITEM;
			case PAYMENT_INFORMATIONS:	
			case PAYMENT_VALUES:
			case STORNO_VALUES:
				return PaymentInformation.CONTENT_TYPE_DIR;
					
			/* REGISTRATION STATES */	
			case REGISTRATION_STATES_ID:
				return RegistrationState.CONTENT_TYPE_ITEM;
			case REGISTRATION_STATES:	
			case REGISTRATION_STATES_FOR_USER:
			case REGISTRATION_STATES_FOR_EVENT:
				return RegistrationState.CONTENT_TYPE_DIR;
							
			/* EVENT INSTITUTION MANAGERS */
			case EVENT_INSTITUTION_MANAGERS_ID:
				return EventInstitutionManager.CONTENT_TYPE_ITEM;
			case EVENT_INSTITUTION_MANAGERS_FOR_USER:
			case EVENT_INSTITUTION_MANAGERS_FOR_EVENT:
			case EVENT_INSTITUTION_MANAGERS_FOR_INSTITUTION:	
				return EventInstitutionManager.CONTENT_TYPE_DIR;
						
			/* INSTITUTIONS */
			case INSTITUTIONS_ID:
				return Institution.CONTENT_TYPE_ITEM;
			case INSTITUTIONS:		
			case INSTITUTIONS_MANAGEABLE_BY_USER:		
			case INSTITUTIONS_FOR_EVENT:
				return Institution.CONTENT_TYPE_DIR;
			
			default:
				return null;
				
		}
	}

	/* EVENTs */	
	public static final int EVENTS_ID = 1;
	public static final int EVENTS_REGISTERED = 2;
	public static final int EVENTS_AVAILABLE = 3;
	public static final int EVENTS_MANAGEABLE = 4;

	/* USERs */
	public static final int USERS = 5;
	public static final int USERS_ID = 6;
	public static final int USERS_EMAIL = 7;
	public static final int USERS_FOR_EVENT = 8;
	public static final int USERS_FOR_INSTITUTION = 9;

	/* REGISTRATION STATEs */
	public static final int REGISTRATION_STATES = 10;
	public static final int REGISTRATION_STATES_ID = 11;
	public static final int REGISTRATION_STATES_FOR_EVENT = 12;
	public static final int REGISTRATION_STATES_FOR_USER = 13;

	/* PAYMENT INFROMATIONs */
	public static final int PAYMENT_INFORMATIONS = 14;
	public static final int PAYMENT_INFORMATIONS_ID = 15;
	public static final int PAYMENT_VALUES = 16;
	public static final int STORNO_VALUES = 17;	

	/* EVENT ISNTITUTION MANAGER */
	public static final int EVENT_INSTITUTION_MANAGERS_ID = 18;
	public static final int EVENT_INSTITUTION_MANAGERS_FOR_EVENT = 19;
	public static final int EVENT_INSTITUTION_MANAGERS_FOR_USER = 20;
	public static final int EVENT_INSTITUTION_MANAGERS_FOR_INSTITUTION = 21;

	/* INSTITUTIONS */
	public static final int INSTITUTIONS = 22;
	public static final int INSTITUTIONS_ID = 23;	
	public static final int INSTITUTIONS_MANAGEABLE_BY_USER = 24;
	public static final int INSTITUTIONS_FOR_EVENT = 25;

	/* COUNTRIES */
	// Zatím nepodporovány
	public static final int COUNTRIES = 26;
	public static final int COUNTRIES_ID = 27;

	static {
		mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		mUriMatcher.addURI(AUTHORITY, "events/#", EVENTS_ID);
		mUriMatcher.addURI(AUTHORITY, "events/registered", EVENTS_REGISTERED);
		mUriMatcher.addURI(AUTHORITY, "events/available", EVENTS_AVAILABLE);
		mUriMatcher.addURI(AUTHORITY, "events/manageable", EVENTS_MANAGEABLE);

		mUriMatcher.addURI(AUTHORITY, "users*", USERS);
		mUriMatcher.addURI(AUTHORITY, "users/byEmail/*", USERS_EMAIL);
		mUriMatcher.addURI(AUTHORITY, "users/#", USERS_ID);
		mUriMatcher.addURI(AUTHORITY, "users/forEvent", USERS_FOR_EVENT);
		mUriMatcher.addURI(AUTHORITY, "users/forInstitution", USERS_FOR_INSTITUTION);

		mUriMatcher.addURI(AUTHORITY, "paymentInformations", PAYMENT_INFORMATIONS);	
		mUriMatcher.addURI(AUTHORITY, "paymentInformations/#", PAYMENT_INFORMATIONS_ID);	
		mUriMatcher.addURI(AUTHORITY, "paymentValues", PAYMENT_VALUES);		
		mUriMatcher.addURI(AUTHORITY, "stornoValues", STORNO_VALUES);		

		mUriMatcher.addURI(AUTHORITY, "registrationStates", REGISTRATION_STATES);
		mUriMatcher.addURI(AUTHORITY, "registrationStates/#", REGISTRATION_STATES_ID);
		mUriMatcher.addURI(AUTHORITY, "registrationStates/forEvent", REGISTRATION_STATES_FOR_EVENT);
		mUriMatcher.addURI(AUTHORITY, "registrationStates/forUser",	REGISTRATION_STATES_FOR_USER);

		mUriMatcher.addURI(AUTHORITY, "institutions", INSTITUTIONS);
		mUriMatcher.addURI(AUTHORITY, "institutions/#", INSTITUTIONS_ID);		
		mUriMatcher.addURI(AUTHORITY, "institutions/forEvent",	INSTITUTIONS_FOR_EVENT);
		mUriMatcher.addURI(AUTHORITY, "institutions/manageable",INSTITUTIONS_MANAGEABLE_BY_USER);

		mUriMatcher.addURI(AUTHORITY, "eventInstitutionManagers/#",	EVENT_INSTITUTION_MANAGERS_ID);
		mUriMatcher.addURI(AUTHORITY, "eventInstitutionManagers/forEvent", EVENT_INSTITUTION_MANAGERS_FOR_EVENT);
		mUriMatcher.addURI(AUTHORITY, "eventInstitutionManagers/forUser", EVENT_INSTITUTION_MANAGERS_FOR_USER);
		mUriMatcher.addURI(AUTHORITY, "eventInstitutionManagers/forInstitution", EVENT_INSTITUTION_MANAGERS_FOR_INSTITUTION);

		mUriMatcher.addURI(AUTHORITY, "countries", COUNTRIES);
		mUriMatcher.addURI(AUTHORITY, "countries/#", COUNTRIES_ID);

	}

}
